﻿using NewAI.Game;
using NewAI.Tools;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace NewAI.FSM.TankFSM
{
    /// <summary>
    /// 枚举类型，对战时可能出现的站位类型
    /// </summary>
    public enum FightSituation
    {
        MaShape,//马字型站位
        StraightLineShape,//直线型站位
        LongMaShape,//长马字型站位
        OtherShape,//其他类型站位
    }

    public class TankFightState : State<TankAI>
    {
        int myX;//当前坦克X坐标
        int enX;//敌方坦克X坐标
        int myY;//当前坦克Y坐标
        int enY;//敌方坦克Y坐标
        int offsetX;//敌我坦克X坐标之差的绝对值
        int offsetY;//敌我坦克Y坐标之差的绝对值
        TankAI entity;


        public override void Enter(TankAI entity)
        {
            this.entity = entity;
            myX = entity.MyTankInfo.Pos.X;
            enX = entity.TargetTankInfo.Pos.X;
            myY = entity.MyTankInfo.Pos.Y;
            enY = entity.TargetTankInfo.Pos.Y;
            offsetX = Math.Abs(myX - enX);
            offsetY = Math.Abs(myY - enY);

            if (entity.TargetTankInfo.Pos.X == -1 || entity.TargetTankInfo.Pos.Y == -1)
            {
                //在没有目标坦克情况下战斗
                HasNotTargetTank();
            }
            else
            {
                //在有目标坦克情况下战斗
                HasTargetTank();
            }
        }

        /// <summary>
        /// 在没有目标tank的情况下战斗
        /// </summary>
        private void HasNotTargetTank()
        {
            BulletType bulletType;
            if (entity.DefaultFightDirection.UseSuperBullet)
                bulletType = BulletType.Super;
            else
                bulletType = BulletType.Normal;
            SendActionObj(entity.DefaultFightDirection.Fire, entity.DefaultFightDirection.Move, bulletType);
        }

        /// <summary>
        /// 在有目标tank的情况下战斗
        /// </summary>
        private void HasTargetTank()
        {
            Direction? fireDir;
            FightSituation fightSituation = ScanSituation();
            entity.FightMethod = Enum.GetName(typeof(FightSituation), fightSituation);

            switch (fightSituation)
            {
                case FightSituation.MaShape:
                    fireDir = FightInMaShape();
                    SendActionObj(fireDir, entity.DefaultFightDirection.Move, BulletType.Normal);
                    break;
                case FightSituation.StraightLineShape:
                    fireDir = FightInStraightLineShape();
                    SendActionObj(fireDir, fireDir, BulletType.Normal);
                    break;
                case FightSituation.LongMaShape:
                    fireDir = FightInLongMaShape();
                    SendActionObj(fireDir, fireDir, BulletType.Normal);
                    break;
                case FightSituation.OtherShape:
                    BulletType bulletType;
                    if (entity.DefaultFightDirection.UseSuperBullet)
                        bulletType = BulletType.Super;
                    else
                        bulletType = BulletType.Normal;
                    SendActionObj(entity.DefaultFightDirection.Fire, entity.DefaultFightDirection.Move, bulletType);
                    break;
                default:
                    PubliceMessage.DebugMessage.Call(null, new FSMEventEventArg($"错误！战术解析错误"));
                    break;
            }
        }

        /// <summary>
        /// 判断敌我站位
        /// </summary>
        /// <param name="entity"></param>
        /// <returns></returns>
        private FightSituation ScanSituation()
        {
            if (myX - enX == 0 || myY - enY == 0)
                return FightSituation.StraightLineShape;
            else if (offsetX == 2 && offsetY == 1)
                return FightSituation.MaShape;
            else if (offsetX == 1 && offsetY == 2)
                return FightSituation.MaShape;
            else if (offsetX == 2 && offsetY == 5)
                return FightSituation.LongMaShape;
            else if (offsetX == 5 && offsetY == 2)
                return FightSituation.LongMaShape;
            else
                return FightSituation.OtherShape;
        }

        /// <summary>
        /// 直线型战斗
        /// </summary>
        /// <param name="entity"></param>
        /// <returns></returns>
        private Direction? FightInStraightLineShape()
        {
            Direction? fireAndMovDir;
            if (myX - enX > 0)
                fireAndMovDir = Direction.Left;
            else if (myX - enX < 0)
                fireAndMovDir = Direction.Right;
            else if (myY - enY > 0)
                fireAndMovDir = Direction.Up;
            else if (myY - enY < 0)
                fireAndMovDir = Direction.Down;
            else
            {
                fireAndMovDir = null;
                PubliceMessage.DebugMessage.Call(null, new FSMEventEventArg("错误，直线型战术分析错误"));
            }
            return fireAndMovDir;
        }

        /// <summary>
        /// 马字型战斗
        /// </summary>
        /// <param name="entity"></param>
        /// <returns></returns>
        private Direction? FightInMaShape()
        {
            Direction? fireDir;
            if (offsetX == 2)
            {
                if (myX - enX > 0)
                    fireDir = Direction.Left;
                else if (myX - enX < 0)
                    fireDir = Direction.Right;
                else
                {
                    fireDir = null;
                    PubliceMessage.DebugMessage.Call(null, new FSMEventEventArg("错误！马字型战术分析出错！"));
                }
            }
            else if (offsetY == 2)
            {
                if (myY - enY > 0)
                    fireDir = Direction.Up;
                else if (myY - enY < 0)
                    fireDir = Direction.Down;
                else
                {
                    fireDir = null;
                    PubliceMessage.DebugMessage.Call(null, new FSMEventEventArg("错误！马字型战术分析出错！"));
                }
            }
            else
            {
                fireDir = null;
                PubliceMessage.DebugMessage.Call(null, new FSMEventEventArg("错误！马字型战术分析出错！"));
            }

            return fireDir;
        }

        /// <summary>
        /// 长马字型战斗
        /// </summary>
        /// <param name="entity"></param>
        /// <returns></returns>
        private Direction? FightInLongMaShape()
        {
            Direction? fireAndMovDir;
            if (offsetX == 5)
            {
                if (myX - enX > 0)
                    fireAndMovDir = Direction.Left;
                else if (myX - enX < 0)
                    fireAndMovDir = Direction.Right;
                else
                {
                    fireAndMovDir = null;
                    PubliceMessage.DebugMessage.Call(null, new FSMEventEventArg("出错！长马字型战术分析出错！"));
                }
            }
            else if (offsetY == 5)
            {
                if (myY - enY > 0)
                    fireAndMovDir = Direction.Up;
                else if (myY - enY < 0)
                    fireAndMovDir = Direction.Down;
                else
                {
                    fireAndMovDir = null;
                    PubliceMessage.DebugMessage.Call(null, new FSMEventEventArg("出错！长马字型战术分析出错！"));
                }
            }
            else
            {
                fireAndMovDir = null;
                PubliceMessage.DebugMessage.Call(null, new FSMEventEventArg("出错！长马字型战术分析出错！"));
            }

            return fireAndMovDir;
        }

        ///// <summary>
        ///// 在没有符合的战术情况下，向敌人开去，进行无指令开火
        ///// </summary>
        ///// <returns></returns>
        //private Direction? FightInOtherShape()
        //{
        //    List<Point> path;
        //    Direction? dir;
        //    try
        //    {
        //        AStarPro.Astar(entity.Map, entity.MyTankInfo.Pos, entity.TargetTankInfo.Pos, out path);
        //        if (path.Count <= 1)
        //        {
        //            dir = null;
        //            return dir;
        //        }
        //        else
        //        {
        //            if (path[1].X - path[0].X > 0)
        //                dir = Direction.Right;
        //            else if (path[1].X - path[0].X < 0)
        //                dir = Direction.Left;
        //            else if (path[1].Y - path[0].Y > 0)
        //                dir = Direction.Down;
        //            else if (path[1].Y - path[0].Y < 0)
        //                dir = Direction.Up;
        //            else
        //                dir = null;

        //            return dir;
        //        }

        //    }
        //    catch (Exception)
        //    {
        //        dir = null;
        //        return dir;
        //    }
        //}

        ///// <summary>
        ///// AStar判断是否向指定相邻位置移动
        ///// </summary>
        ///// <param name="movDir"></param>
        ///// <returns></returns>
        //private bool AStarDecideWhetherMov(Direction? movDir)
        //{
        //    List<Point> path;
        //    Point endPoint;
        //    switch (movDir)
        //    {
        //        case Direction.Up:
        //            endPoint = new Point(myX, myY - 1);
        //            try
        //            {
        //                AStarPro.Astar(entity.Map, entity.MyTankInfo.Pos, endPoint, out path);
        //                if (path.Count <= 1)
        //                    return false;
        //            }
        //            catch (Exception)
        //            {
        //                return false;
        //            }
        //            break;
        //        case Direction.Down:
        //            endPoint = new Point(myX, myY + 1);
        //            try
        //            {
        //                AStarPro.Astar(entity.Map, entity.MyTankInfo.Pos, endPoint, out path);
        //                if (path.Count <= 1)
        //                    return false;
        //            }
        //            catch (Exception)
        //            {
        //                return false;
        //            }
        //            break;
        //        case Direction.Left:
        //            endPoint = new Point(myX - 1, myY);
        //            try
        //            {
        //                AStarPro.Astar(entity.Map, entity.MyTankInfo.Pos, endPoint, out path);
        //                if (path.Count <= 1)
        //                    return false;
        //            }
        //            catch (Exception)
        //            {
        //                return false;
        //            }
        //            break;
        //        case Direction.Right:
        //            endPoint = new Point(myX + 1, myY);
        //            try
        //            {
        //                AStarPro.Astar(entity.Map, entity.MyTankInfo.Pos, endPoint, out path);
        //                if (path.Count <= 1)
        //                    return false;
        //            }
        //            catch (Exception)
        //            {
        //                return false;
        //            }
        //            break;
        //        default:
        //            return false;
        //    }
        //    return true;
        //}

        /// <summary>
        /// 构建及发送当前坦克的Action指令
        /// </summary>
        /// <param name="fireDirection"></param>
        /// <param name="movDirection"></param>
        private void SendActionObj(Direction? fireDirection, Direction? movDirection, BulletType bulletType)
        {
            ActionObj obj = new ActionObj(GV.OurTeam.TeamID, entity.MyTankInfo.TankID, movDirection, fireDirection, bulletType);
            entity.ActionObjToJsonAnalyzer.Call(null, new FSMEventEventArg(obj));
        }

    }
}
